package org.example;

import cn.hutool.core.io.resource.ResourceUtil;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.example.binding.XMLStatementBuilder;
import org.example.mapping.ParameterMap;
import org.example.mapping.ParameterMapping;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

public class XmlMapperBuilder {


    private String resource;


    private Configuration configuration;


    private String namespace;


    private Class<?> mapperInterface;



    private Element root;


    public XmlMapperBuilder(String resource,Configuration configuration) {
        this.resource = resource;
        this.configuration = configuration;
    }


    public void parse() {
        InputStream inputStream = ResourceUtil.getStream(resource);
        Reader reader = new InputStreamReader(inputStream);
        SAXReader config = new SAXReader();
        Document document;
        try {
            document = config.read(reader);
        } catch (DocumentException e) {
            throw new RuntimeException("读取Mapper文件发生错误",e);
        }
        root = document.getRootElement();
        String namespace = root.attributeValue("namespace");
        System.out.println(namespace);
        this.namespace = namespace;

        try {
            Class<?> aClass = Class.forName(namespace);
            this.mapperInterface = aClass;
            configuration.addMapper(aClass);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("找不到命名空间类型： " + this.namespace);
        }
        parseParameterMap(root.elements("parameterMap"));

        List<Element> allStatement = getAllStatement();
        parseStatementNodes(allStatement);

    }



    private void parseStatementNodes(List<Element> list) {
        for (Element element : list) {
            XMLStatementBuilder builder = new XMLStatementBuilder(namespace, element,configuration);
            builder.parse();
        }


    }



    private List<Element> getAllStatement() {
        List<Element> result = new ArrayList<>();
        List<Element> select = root.elements("select");
        if(select != null && !select.isEmpty()) {
            result.addAll(select);
        }
        return result;
    }






    private void parseParameterMap(List<Element> list) {

        for (Element element : list) {
            String id = element.attributeValue("id");
            String type = element.attributeValue("type");
            Class<?> typeClass = null;
            if(type != null && !type.isEmpty()) {
                try {
                    typeClass = Class.forName(type);
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException("解析ParameterMap，获取类型信息发生错误",e);
                }
            }

            List<Element> elementList = element.elements("parameter");
            List<ParameterMapping> mappings = new ArrayList<>();
            for (Element child : elementList) {
                String property = child.attributeValue("property");
                String javaType = child.attributeValue("javaType");
                Class<?> parameterJavaType = null;
                if(javaType != null && !javaType.isEmpty()) {
                    try {
                        parameterJavaType = Class.forName(javaType);
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException("解析ParameterMapping，获取类型信息发生错误",e);
                    }
                }

                ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration,property,parameterJavaType);
                mappings.add(builder.build());
            }


            String parameterMapId =  namespace + "_" + id;
            ParameterMap parameterMap = new ParameterMap();
            parameterMap.setId(parameterMapId);
            parameterMap.setType(type);
            parameterMap.setTypeClass(typeClass);
            parameterMap.setMappingList(mappings);
            configuration.addParameterMap(parameterMap);
        }
    }




}
